package com.cn.lp.jpa.cq.domain;

import com.cn.lp.common.utils.JSONAide;
import com.cn.lp.jpa.cq.CQLogicalType;
import com.cn.lp.jpa.cq.CQOrderType;
import com.cn.lp.log.LogUtils;
import com.google.common.base.Joiner;

import java.util.*;

/**
 * Created by on 2019/8/7.
 */
public class CQSign {

    /**
     * 数据源类型
     */
    private Class<?> fromClass;

    private List<CQSignItem> itemList = new ArrayList<>();

    private List<CQOrderSign> orderList = new ArrayList<>();

    public CQSign(Class<?> fromClass) {
        this.fromClass = fromClass;
    }

    public void markOrder(CQField field, CQOrderType orderType) {
        orderList.add(CQOrderSign.of(field, orderType));
    }

    public void markBlock(CQLogicalType logicalType, boolean start) {
        itemList.add(CQBlockSign.of(logicalType, start));
    }

    public void markCondition(CQLogicalType logicalType, String condition, CQField field1, CQField field2) {
        itemList.add(CQConditionSign.of(logicalType, LogUtils.format("{}#F({}):F({})", condition, field1.getName(), field2.getName())));
    }

    public void markCondition(CQLogicalType logicalType, String condition, CQField field1, Object data) {
        itemList.add(CQConditionSign.of(logicalType, LogUtils.format("{}#F({}):{}", condition, field1.getName(), JSONAide.toJson(data))));
    }

    public void markBetween(CQLogicalType logicalType, CQField field1, Object data1, Object data2) {
        itemList.add(CQConditionSign.of(logicalType, LogUtils.format("{}#F({}):{}-{}", "between", field1.getName(), JSONAide.toJson(data1), JSONAide.toJson(data2))));
    }

    private String createBlock(Deque<CQSignItem> dataList) {
        CQSignItem item = dataList.pollFirst();
        List<String> blockList = new ArrayList<>();
        while (item != null) {
            if (item instanceof CQBlockSign) {
                if (((CQBlockSign) item).isStart()) {
                    String block = createBlock(dataList);
                    if (block != null) {
                        blockList.add(block);
                    }
                } else {
                    if (blockList.size() > 1) {
                        Collections.sort(blockList);
                        StringBuilder sb = new StringBuilder();
                        sb.append("|");
                        sb.append(Joiner.on("-").join(blockList));
                        sb.append("|");
                        return sb.toString();
                    } else if (blockList.size() == 1) {
                        return blockList.get(0);
                    } else {
                        return null;
                    }
                }
            } else {
                blockList.add(LogUtils.format("{}^{}", item.getLogicalType(), item.getText()));
            }
            item = dataList.pollFirst();
        }
        Collections.sort(blockList);
        return Joiner.on("-").join(blockList);
    }

    public String createSign() {
        LinkedList<CQSignItem> itemList = new LinkedList<>(this.itemList);
        CQSignItem item = itemList.pollFirst();
        List<String> blockList = new ArrayList<>();
        while (item != null) {
            if (item instanceof CQBlockSign) {
                String block = createBlock(itemList);
                if (block != null) {
                    blockList.add(block);
                }
            } else {
                blockList.add(LogUtils.format("{}^{}", item.getLogicalType(), item.getText()));
            }
            item = itemList.pollFirst();
        }
        List<String> orderSignList = new ArrayList<>();
        for (CQOrderSign orderSign : orderList) {
            orderSignList.add(LogUtils.format("F({})*{}", orderSign.getField().getName(), orderSign.getOrderType()));
        }
        Collections.sort(blockList);
        if (!orderSignList.isEmpty()) {
            Collections.sort(orderSignList);
            blockList.addAll(orderSignList);
        }
        return Joiner.on(",").join(blockList);
    }

}
